package com.spsoft.vatoutinv.service.vmshzqrdmanage.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.spsoft.core.enums.ResponseEnum;
import com.spsoft.core.exception.BusinessException;
import com.spsoft.core.model.Result;
import com.spsoft.core.model.bo.TokenUser;
import com.spsoft.core.model.leqidmz.param.ConfirmRedConfirmParam;
import com.spsoft.core.model.leqidmz.param.QueryRedConfirmDetailParam;
import com.spsoft.core.model.leqidmz.param.QueryRedConfirmListParam;
import com.spsoft.core.model.leqidmz.response.ConfirmRedConfirmVO;
import com.spsoft.core.model.leqidmz.response.QueryRedConfirmDetailVO;
import com.spsoft.core.model.leqidmz.response.QueryRedConfirmListVO;
import com.spsoft.core.utils.BeanUtils;
import com.spsoft.core.utils.SecurityUtils;
import com.spsoft.core.utils.StringUtil;
import com.spsoft.einvoicetodmz.service.DmzApiClientService;
import com.spsoft.system.entity.NvatOutInvoiceDetails;
import com.spsoft.system.entity.NvatOutInvomapSelf;
import com.spsoft.system.mapper.NvatOutInvoiceDetailsMapper;
import com.spsoft.system.mapper.NvatOutInvomapselfMapper;
import com.spsoft.vatoutinv.constants.CommonConstant;
import com.spsoft.vatoutinv.entity.vmsenterpriseinfo.VmsEnterpriseInfo;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsApprovalHzqrd;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsApprovalHzqrdItem;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsLeqiHzqrd;
import com.spsoft.vatoutinv.entity.vmshzqrdmanage.VmsLeqiHzqrdItem;
import com.spsoft.vatoutinv.enums.CommonEnum;
import com.spsoft.vatoutinv.enums.HzqrdStatusEnum;
import com.spsoft.vatoutinv.model.dto.vmshzqrdmanage.VmsApprovalHzqrdPageDto;
import com.spsoft.vatoutinv.model.vo.vmshzqrdmanage.*;
import com.spsoft.vatoutinv.service.vmsenterpriseinfo.VmsEnterpriseInfoService;
import com.spsoft.vatoutinv.service.vmshzqrdmanage.*;
import com.spsoft.workflow.common.enums.BizStatusEnums;
import com.spsoft.workflow.entity.WfProcessBusiness;
import com.spsoft.workflow.service.ProcessBusinessService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 红字确认单确认 服务实现类
 *
 * @author : chenxudong
 * @date : 2024/1/4 17:14
 */
@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class VmsHzqrdConfirmServiceImpl implements VmsHzqrdConfirmService {

    public static final String LOG_MSG = "(红字确认单确认实现层)";

    private final VmsApprovalHzqrdService vmsApprovalHzqrdService;

    private final VmsApprovalHzqrdItemService vmsApprovalHzqrdItemService;

    private final VmsLeqiHzqrdService vmsLeqiHzqrdService;

    private final VmsLeqiHzqrdItemService vmsLeqiHzqrdItemService;

    private final VmsEnterpriseInfoService vmsEnterpriseInfoService;

    private final ProcessBusinessService processBusinessService;

    private final NvatOutInvoiceDetailsMapper nvatOutInvoiceDetailsMapper;

    private final NvatOutInvomapselfMapper nvatOutInvomapselfMapper;

    private final DmzApiClientService dmzApiClientService;

    @Override
    public Result<IPage<VmsApprovalHzqrdVo>> pageApply(VmsApprovalHzqrdPageDto pageDto) {
        // 分页查询
        Page<VmsApprovalHzqrd> page = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        LambdaQueryWrapper<VmsApprovalHzqrd> wrapper = new LambdaQueryWrapper<>();

        // 查询审批流程类型为红字确认单确认的数据
        wrapper.eq(VmsApprovalHzqrd::getApplyType, CommonEnum.HZQRD_APPROVAL_TYPE_1.getKey());
        // 查询当前机构创建人是自己，或者审批人是自己的数据
        wrapper.eq(VmsApprovalHzqrd::getQydjid, pageDto.getDeptCode());
        wrapper.and(i -> i.eq(VmsApprovalHzqrd::getCreatBy, pageDto.getCreatBy())
                .or()
                .eq(VmsApprovalHzqrd::getApprovalBy, pageDto.getCreatBy()));
        // 查询未删除的数据
        wrapper.eq(VmsApprovalHzqrd::getDelFlag, CommonEnum.DEL_STATUS_0.getKey());
        wrapper.eq(StringUtil.isNotBlank(pageDto.getHzqrxxztdm()), VmsApprovalHzqrd::getHzqrxxztdm, pageDto.getHzqrxxztdm());
        wrapper.eq(StringUtil.isNotBlank(pageDto.getChyydm()), VmsApprovalHzqrd::getChyydm, pageDto.getChyydm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getLzfphm()), VmsApprovalHzqrd::getLzfphm, pageDto.getLzfphm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getHzfpxxqrdbh()), VmsApprovalHzqrd::getHzfpxxqrdbh, pageDto.getHzfpxxqrdbh());
        if (StringUtil.isNotBlank(pageDto.getLzfpkprqq()) && StringUtil.isNotBlank(pageDto.getLzfpkprqz())) {
            // 蓝字发票开票日期起止
            String lzfpkprqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getLzfpkprqq())), CommonConstant.DATE_FORMAT_14);
            String lzfpkprqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getLzfpkprqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("LZKPRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", lzfpkprqq);
            wrapper.apply("LZKPRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", lzfpkprqz);
        }
        if (StringUtil.isNotBlank(pageDto.getHzqrdsqrqq()) && StringUtil.isNotBlank(pageDto.getHzqrdsqrqz())) {
            // 红字确认单申请日期起止
            String hzqrdsqrqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getHzqrdsqrqq())), CommonConstant.DATE_FORMAT_14);
            String hzqrdsqrqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getHzqrdsqrqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("LRRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdsqrqq);
            wrapper.apply("LRRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdsqrqz);
        }
        wrapper.orderByDesc(VmsApprovalHzqrd::getCreatTime, VmsApprovalHzqrd::getId);

        Page<VmsApprovalHzqrd> IPage = vmsApprovalHzqrdService.page(page, wrapper);
        // 将数据库返回数据转换为VO返回前端
        IPage<VmsApprovalHzqrdVo> IPageVo = IPage.convert(item -> {
            VmsApprovalHzqrdVo vo = new VmsApprovalHzqrdVo();
            // 转换数据
            BeanUtils.copyBeanProp(vo, item);
            return vo;
        });

        return Result.OK(IPageVo);
    }

    @Override
    public Result<IPage<VmsLeqiHzqrdVo>> pageHzqrd(VmsApprovalHzqrdPageDto pageDto) {
        // 分页查询
        Page<VmsLeqiHzqrd> page = new Page<>(pageDto.getPageNo(), pageDto.getPageSize());
        LambdaQueryWrapper<VmsLeqiHzqrd> wrapper = new LambdaQueryWrapper<>();

        // 查询当前登录机构的数据
        wrapper.eq(VmsLeqiHzqrd::getQydjid, pageDto.getDeptCode());
        // 仅查询销方录入待购方确认、购方录入待销方确认的数据
        if (StringUtils.isNotBlank(pageDto.getHzqrxxztdm())) {
            wrapper.eq(VmsLeqiHzqrd::getHzqrxxztdm, pageDto.getHzqrxxztdm());
        } else {
            wrapper.in(VmsLeqiHzqrd::getHzqrxxztdm, CommonEnum.HZQRD_STATUS_02.getKey(), CommonEnum.HZQRD_STATUS_03.getKey());
        }
        wrapper.eq(StringUtil.isNotBlank(pageDto.getChyydm()), VmsLeqiHzqrd::getChyydm, pageDto.getChyydm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getLzfphm()), VmsLeqiHzqrd::getLzfphm, pageDto.getLzfphm());
        wrapper.likeRight(StringUtil.isNotBlank(pageDto.getHzfpxxqrdbh()), VmsLeqiHzqrd::getHzfpxxqrdbh, pageDto.getHzfpxxqrdbh());
        if (StringUtil.isNotBlank(pageDto.getLzfpkprqq()) && StringUtil.isNotBlank(pageDto.getLzfpkprqz())) {
            // 蓝字发票开票日期起止
            String lzfpkprqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getLzfpkprqq())), CommonConstant.DATE_FORMAT_14);
            String lzfpkprqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getLzfpkprqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("LZKPRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", lzfpkprqq);
            wrapper.apply("LZKPRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", lzfpkprqz);
        }
        if (StringUtil.isNotBlank(pageDto.getHzqrdsqrqq()) && StringUtil.isNotBlank(pageDto.getHzqrdsqrqz())) {
            // 红字确认单申请日期起止
            String hzqrdsqrqq = DateUtil.format(DateUtil.beginOfDay(DateUtil.parseDate(pageDto.getHzqrdsqrqq())), CommonConstant.DATE_FORMAT_14);
            String hzqrdsqrqz = DateUtil.format(DateUtil.endOfDay(DateUtil.parseDate(pageDto.getHzqrdsqrqz())), CommonConstant.DATE_FORMAT_14);
            wrapper.apply("LRRQ >= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdsqrqq);
            wrapper.apply("LRRQ <= TO_DATE({0},'yyyy-mm-dd hh24:mi:ss')", hzqrdsqrqz);
        }
        wrapper.orderByDesc(VmsLeqiHzqrd::getLrrq, VmsLeqiHzqrd::getId);

        Page<VmsLeqiHzqrd> IPage = vmsLeqiHzqrdService.page(page, wrapper);
        // 将数据库返回数据转换为VO返回前端
        IPage<VmsLeqiHzqrdVo> IPageVo = IPage.convert(item -> {
            VmsLeqiHzqrdVo vo = new VmsLeqiHzqrdVo();
            // 转换数据
            BeanUtils.copyBeanProp(vo, item);
            vo.setLzjshj(item.getLzhjje().add(item.getLzhjse()));
            return vo;
        });

        return Result.OK(IPageVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> getHzqrd(TokenUser tokenUser) {
        try {
            // 组装参数，调用乐企查询数电红字确认单列表信息接口
            VmsEnterpriseInfo enterpriseInfo = vmsEnterpriseInfoService.getInfoByRedis(tokenUser.getDeptCode());
            if (enterpriseInfo == null) {
                return Result.ERROR(ResponseEnum.ENTERPRISEINFO_ERROR);
            }

            List<QueryRedConfirmListParam> paramList = new ArrayList<>();
            QueryRedConfirmListParam param1 = new QueryRedConfirmListParam();
            // 用户角色类型 0：销方
            param1.setYhjslx(CommonEnum.LRFSF_XSF.getKey());
            param1.setXsfnsrsbh(enterpriseInfo.getNsrsbh());
            param1.setXsfmc(enterpriseInfo.getNsrmc());
            // 查询一周的数据
            param1.setLrrqq(DateUtil.format(DateUtil.lastWeek(), CommonConstant.DATE_FORMAT_8));
            param1.setLrrqz(DateUtil.format(new Date(), CommonConstant.DATE_FORMAT_8));
            // 分页查询
            param1.setPageNumber(1);
            param1.setPageSize(100);
            paramList.add(param1);

            QueryRedConfirmListParam param2 = new QueryRedConfirmListParam();
            // 用户角色类型 1：购方
            param2.setYhjslx(CommonEnum.LRFSF_GMF.getKey());
            param2.setGmfnsrsbh(enterpriseInfo.getNsrsbh());
            param2.setGmfmc(enterpriseInfo.getNsrmc());
            // 查询一周的数据
            param2.setLrrqq(DateUtil.format(DateUtil.lastWeek(), CommonConstant.DATE_FORMAT_8));
            param2.setLrrqz(DateUtil.format(new Date(), CommonConstant.DATE_FORMAT_8));
            // 分页查询
            param2.setPageNumber(1);
            param2.setPageSize(100);
            paramList.add(param2);

            int successCount = 0;
            for (QueryRedConfirmListParam param : paramList) {
                // 调用乐企接口同步红字确认单
                int num = syncLeqiHzqrd(param, tokenUser);
                successCount = successCount + num;
                while (num == 100) {
                    // 调用成功后，查询下一页数据
                    param.setPageNumber(param.getPageNumber() + 1);
                    num = syncLeqiHzqrd(param, tokenUser);
                    successCount = successCount + num;
                }
            }
            return Result.OK("查询成功！共查询到" + successCount + "条符合条件的红字确认单信息！");
        } catch (BusinessException e) {
            log.error("{}查询红字确认单出现业务异常", LOG_MSG, e);
            return Result.ERRORT(e.getCode(), e.getMsg());
        } catch (Exception e) {
            log.error("{}查询红字确认单出现未知异常", LOG_MSG, e);
            return Result.ERROR("查询失败！失败原因：" + e.getMessage());
        }
    }

    @Override
    public Result<VmsApprovalHzqrdTotalSimpleVo> fastAdd(String hzxxqrdbh, Long applyId) {
        if (StringUtils.isBlank(hzxxqrdbh)) {
            return Result.ERROR(ResponseEnum.HZXXQRDBH_EMPTY_ERROR);
        }

        LambdaQueryWrapper<VmsLeqiHzqrd> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VmsLeqiHzqrd::getHzfpxxqrdbh, hzxxqrdbh);
        wrapper.eq(VmsLeqiHzqrd::getQydjid, SecurityUtils.getDeptCode());
        VmsLeqiHzqrd leqiHzqrd = vmsLeqiHzqrdService.getOne(wrapper);
        if (leqiHzqrd == null) {
            return Result.ERROR(ResponseEnum.HZQRD_NOT_FIND_ERROR);
        }

        // 调用乐企接口查询数电红字确认单明细信息
        QueryRedConfirmDetailParam itemParam = new QueryRedConfirmDetailParam();
        itemParam.setXsfnsrsbh(leqiHzqrd.getXsfnsrsbh());
        itemParam.setUuid(leqiHzqrd.getUuid());
        itemParam.setCreateUser(SecurityUtils.getUserCode());
        itemParam.setDeptCode(SecurityUtils.getDeptCode());
        Result<QueryRedConfirmDetailVO> itemResult = dmzApiClientService.queryRedConfirmDetail(itemParam, null);
        if (!ResponseEnum.SUCCESS.getCode().equals(itemResult.getCode())) {
            return Result.ERRORT(itemResult.getCode(), itemResult.getMessage());
        }
        QueryRedConfirmDetailVO itemResultData = itemResult.getData();
        // 将乐企返回的红字确认单信息同步到本地
        vmsLeqiHzqrdService.syncSingleLeqiHzqrd(itemResultData, SecurityUtils.getTokenUser());

        /*
        当红字确认单状态为“02”销方录入待购方确认时，需校验蓝字发票是否为当前企业进项发票
        当红字确认单状态为“03”购方录入待销方确认时，需校验蓝字发票是否为当前企业销项发票
        */
        // 以乐企返回的红字确认单状态为准
        String hzqrxxztdm = itemResultData.getHzqrxxztDm();
        if (HzqrdStatusEnum.HZQRD_STATUS_02.getKey().equals(hzqrxxztdm)) {
            // 校验蓝字发票是否为当前企业进项发票
            log.info("{}校验蓝字发票是否为当前企业进项发票", LOG_MSG);
            // 校验当前机构是否为销方，如果是，不允许确认
            String nsrsbh = vmsEnterpriseInfoService.getNsrsbh();
            if (StringUtils.isNotBlank(nsrsbh) && nsrsbh.equals(leqiHzqrd.getXsfnsrsbh())) {
                return Result.ERRORT(ResponseEnum.BUSINESS_ERROR.getCode(),
                        "红字确认单状态为：" + HzqrdStatusEnum.HZQRD_STATUS_02.getValue() + "，且当前机构为销方，无法进行红字确认单确认操作，请确认");
            }
        } else if (HzqrdStatusEnum.HZQRD_STATUS_03.getKey().equals(hzqrxxztdm)) {
            // 校验蓝字发票是否为当前企业销项发票
            log.info("{}校验蓝字发票是否为当前企业销项发票", LOG_MSG);
            // 校验当前机构是否为购方，如果是，不允许确认
            String nsrsbh = vmsEnterpriseInfoService.getNsrsbh();
            if (StringUtils.isNotBlank(nsrsbh) && nsrsbh.equals(leqiHzqrd.getGmfnsrsbh())) {
                return Result.ERRORT(ResponseEnum.BUSINESS_ERROR.getCode(),
                        "红字确认单状态为：" + HzqrdStatusEnum.HZQRD_STATUS_03.getValue() + "，且当前机构为购方，无法进行红字确认单确认操作，请确认");
            }
        } else {
            String value = HzqrdStatusEnum.getValueByKey(hzqrxxztdm);
            return Result.ERRORT(ResponseEnum.BUSINESS_ERROR.getCode(), "红字确认单状态为：" + value + "，无法进行红字确认单确认操作，请确认");
        }

        // 判断当前红字确认单是否有在途的红字确认单确认流程，若存在则不允许再次提交红字确认单确认流程
        LambdaQueryWrapper<VmsApprovalHzqrd> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VmsApprovalHzqrd::getHzfpxxqrdbh, hzxxqrdbh);
        queryWrapper.eq(VmsApprovalHzqrd::getApplyType, CommonEnum.HZQRD_APPROVAL_TYPE_1.getKey());
        queryWrapper.eq(VmsApprovalHzqrd::getDelFlag, CommonEnum.DEL_STATUS_0.getKey());
        List<VmsApprovalHzqrd> hzqrdList = vmsApprovalHzqrdService.list(queryWrapper);
        if (CollectionUtil.isNotEmpty(hzqrdList) && applyId != null) {
            // 保存未提交时，首页点击办理进入，删除本次未提交的流程
            hzqrdList.removeIf(vmsApprovalHzqrd -> applyId.equals(vmsApprovalHzqrd.getApplyId()));
        }
        if (CollectionUtil.isNotEmpty(hzqrdList)) {
            for (VmsApprovalHzqrd approvalHzqrd : hzqrdList) {
                LambdaQueryWrapper<WfProcessBusiness> query = new LambdaQueryWrapper<>();
                query.eq(WfProcessBusiness::getId, approvalHzqrd.getApplyId());
                WfProcessBusiness processBusiness = processBusinessService.getOne(query);
                // 流程状态为4、5说明流程已结束
                if (processBusiness != null && !StrUtil.equalsAny(processBusiness.getBusStatus(),
                        BizStatusEnums.BUSINESS_STATUS_4.getStatus(), BizStatusEnums.BUSINESS_STATUS_5.getStatus())) {
                    return Result.ERROR(ResponseEnum.HZQRD_CONFIRM_PROCESS_NOT_FINISH_ERROR);
                }
            }
        }

        // todo 通过“发票用途状态信息查询”接口查询蓝字发票状态信息
        // 发票用途，调不了接口先固定为1
        String fpyt = "1";
        // 发票入账状态，调不了接口先固定为02
        String fprzzt = "02";

        // 判断购买方是否抵扣/入账
        String gmfsfdkrz = CommonConstant.STR_N;
        // 乐企进项接口通了之后在校验
        /*if (CommonEnum.INVOICE_USE_1.getKey().equals(fpyt) || CommonEnum.INVOICE_RECORD_02.getKey().equals(fprzzt)) {
            gmfsfdkrz = CommonConstant.STR_Y;
        } else {
            gmfsfdkrz = CommonConstant.STR_N;
        }*/

        // 判断冲红类型 部分还是全额冲红
        String chlx = judgeChlx(leqiHzqrd);

        LambdaQueryWrapper<VmsLeqiHzqrdItem> query = new LambdaQueryWrapper<>();
        query.eq(VmsLeqiHzqrdItem::getHzqrdId, leqiHzqrd.getId());
        query.orderByAsc(VmsLeqiHzqrdItem::getXh);
        List<VmsLeqiHzqrdItem> leqiHzqrdItems = vmsLeqiHzqrdItemService.list(query);
        List<VmsApprovalHzqrdItemVo> leqiHzqrdItemVoList = BeanUtils.copyListProperties(leqiHzqrdItems, VmsApprovalHzqrdItemVo::new, (s, t) -> {
            if (StringUtils.isNotBlank(s.getFpspdj())) {
                t.setDj(s.getFpspdj());
            }
            if (StringUtils.isNotBlank(s.getFpspsl())) {
                t.setSl(s.getFpspsl());
            }
            t.setSlv(s.getSl1());
        });

        VmsApprovalHzqrdTotalSimpleVo totalVo = new VmsApprovalHzqrdTotalSimpleVo();
        VmsApprovalHzqrdSimpleVo hzqrdSimpleVo = new VmsApprovalHzqrdSimpleVo();

        hzqrdSimpleVo.setLzfpdm(leqiHzqrd.getLzfpdm());
        hzqrdSimpleVo.setLzfphm(leqiHzqrd.getLzfphm());
        hzqrdSimpleVo.setHzfpxxqrdbh(leqiHzqrd.getHzfpxxqrdbh());
        hzqrdSimpleVo.setLrfsf(leqiHzqrd.getLrfsf());
        hzqrdSimpleVo.setXsfmc(leqiHzqrd.getXsfmc());
        hzqrdSimpleVo.setXsfnsrsbh(leqiHzqrd.getXsfnsrsbh());
        hzqrdSimpleVo.setGmfmc(leqiHzqrd.getGmfmc());
        hzqrdSimpleVo.setGmfnsrsbh(leqiHzqrd.getGmfnsrsbh());
        hzqrdSimpleVo.setChyydm(leqiHzqrd.getChyydm());
        hzqrdSimpleVo.setChlx(chlx);
        hzqrdSimpleVo.setGmfsfdkrz(gmfsfdkrz);

        totalVo.setVmsApprovalHzqrdSimpleVo(hzqrdSimpleVo);
        totalVo.setVmsApprovalHzqrdItemVoList(leqiHzqrdItemVoList);
        return Result.OK(totalVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> saveConfirm(Long applyId, String hzxxqrdbh) {
        // 保存数据时也要走一遍快速添加的校验
        Result<VmsApprovalHzqrdTotalSimpleVo> result = fastAdd(hzxxqrdbh, applyId);
        if (!ResponseEnum.SUCCESS.getCode().equals(result.getCode())) {
            return Result.ERROR(result.getCode(), result.getMessage());
        }
        VmsApprovalHzqrdSimpleVo hzqrdSimpleVo = result.getData().getVmsApprovalHzqrdSimpleVo();

        LambdaQueryWrapper<VmsLeqiHzqrd> hzqrdQuery = new LambdaQueryWrapper<>();
        hzqrdQuery.eq(VmsLeqiHzqrd::getHzfpxxqrdbh, hzxxqrdbh);
        hzqrdQuery.eq(VmsLeqiHzqrd::getQydjid, SecurityUtils.getDeptCode());
        VmsLeqiHzqrd leqiHzqrd = vmsLeqiHzqrdService.getOne(hzqrdQuery);
        if (leqiHzqrd == null) {
            return Result.ERROR(ResponseEnum.HZQRD_NOT_FIND_ERROR);
        }

        // 组装主信息入库数据
        VmsApprovalHzqrd hzqrd = new VmsApprovalHzqrd();
        BeanUtils.copyBeanProp(hzqrd, leqiHzqrd);
        hzqrd.setId(null);
        hzqrd.setApplyId(applyId);
        hzqrd.setApplyType(CommonEnum.HZQRD_APPROVAL_TYPE_1.getKey());
        hzqrd.setGmfsfdkrz(hzqrdSimpleVo.getGmfsfdkrz());
        // todo 冲红类型 待定
        hzqrd.setChlx(hzqrdSimpleVo.getChlx());
        hzqrd.setQydjid(SecurityUtils.getDeptCode());
        hzqrd.setCreatTime(new Date());
        hzqrd.setCreatBy(SecurityUtils.getUserCode());
        hzqrd.setUpdateTime(new Date());
        hzqrd.setUpdateBy(SecurityUtils.getUserCode());

        // 组装明细信息入库数据
        LambdaQueryWrapper<VmsLeqiHzqrdItem> hzqrdItemQuery = new LambdaQueryWrapper<>();
        hzqrdItemQuery.eq(VmsLeqiHzqrdItem::getHzqrdId, leqiHzqrd.getId());
        hzqrdItemQuery.orderByAsc(VmsLeqiHzqrdItem::getXh);
        List<VmsLeqiHzqrdItem> leqiHzqrdItemList = vmsLeqiHzqrdItemService.list(hzqrdItemQuery);
        List<VmsApprovalHzqrdItem> approvalHzqrdItemList = BeanUtils.copyListProperties(leqiHzqrdItemList, VmsApprovalHzqrdItem::new);

        // 主表数据入库
        LambdaQueryWrapper<VmsApprovalHzqrd> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VmsApprovalHzqrd::getApplyId, applyId);
        VmsApprovalHzqrd approvalHzqrd = vmsApprovalHzqrdService.getOne(wrapper);
        if (approvalHzqrd == null) {
            vmsApprovalHzqrdService.save(hzqrd);
        } else {
            hzqrd.setId(approvalHzqrd.getId());
            hzqrd.setCreatTime(approvalHzqrd.getCreatTime());
            hzqrd.setCreatBy(approvalHzqrd.getCreatBy());
            vmsApprovalHzqrdService.updateById(hzqrd);
            // 明细表数据删除后再重新入库
            LambdaQueryWrapper<VmsApprovalHzqrdItem> itemWrapper = new LambdaQueryWrapper<>();
            itemWrapper.eq(VmsApprovalHzqrdItem::getHzqrdId, hzqrd.getId());
            vmsApprovalHzqrdItemService.remove(itemWrapper);
        }
        approvalHzqrdItemList = approvalHzqrdItemList.stream().peek(hzqrdItem -> hzqrdItem.setHzqrdId(hzqrd.getId())).collect(Collectors.toList());
        vmsApprovalHzqrdItemService.saveBatch(approvalHzqrdItemList);

        return Result.OK();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> revokeConfirm(Long id) {
        LambdaQueryWrapper<VmsApprovalHzqrd> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(VmsApprovalHzqrd::getId, id);
        VmsApprovalHzqrd approvalHzqrd = vmsApprovalHzqrdService.getOne(wrapper);
        if (approvalHzqrd == null) {
            return Result.ERROR(ResponseEnum.HZQRD_NOT_FIND_ERROR);
        }
        // 红字确认单撤销时要求红字确认单有效状态为有效且未开具红票
        if (!CommonEnum.HZQRD_YXBZ_YES.getKey().equals(approvalHzqrd.getYxbz()) || !CommonEnum.YKJHZFP_NO.getKey().equals(approvalHzqrd.getYkjhzfpbz())) {
            return Result.ERROR(ResponseEnum.HZQRD_REVOKE_ERROR);
        }
        // 红字确认单撤销时要求红字确认单状态为：04：购销双方已确认
        if (!CommonEnum.HZQRD_STATUS_04.getKey().equals(approvalHzqrd.getHzqrxxztdm())) {
            return Result.ERROR(ResponseEnum.HZQRD_REVOKE_ERROR3);
        }
        // 调用乐企数电红字确认单确认接口完成红字确认单撤销
        ConfirmRedConfirmParam param = new ConfirmRedConfirmParam();
        param.setXsfnsrsbh(approvalHzqrd.getXsfnsrsbh());
        param.setUuid(approvalHzqrd.getUuid());
        param.setHzqrdbh(approvalHzqrd.getHzfpxxqrdbh());
        param.setQrlx(CommonEnum.HZQRD_QRLX_C.getKey());
        param.setCreateUser(SecurityUtils.getUserCode());
        param.setDeptCode(SecurityUtils.getDeptCode());
        Result<ConfirmRedConfirmVO> result = dmzApiClientService.confirmRedConfirm(param, null);
        if (!ResponseEnum.SUCCESS.getCode().equals(result.getCode())) {
            return Result.ERRORT(result.getCode(), result.getMessage());
        }
        log.info("{}调用DMZ数电红字确认单确认接口完成红字确认单撤销成功", LOG_MSG);

        // 调用乐企接口查询数电红字确认单明细信息
        QueryRedConfirmDetailParam itemParam = new QueryRedConfirmDetailParam();
        itemParam.setXsfnsrsbh(approvalHzqrd.getXsfnsrsbh());
        itemParam.setUuid(approvalHzqrd.getUuid());
        itemParam.setCreateUser(SecurityUtils.getUserCode());
        itemParam.setDeptCode(SecurityUtils.getDeptCode());
        Result<QueryRedConfirmDetailVO> itemResult = dmzApiClientService.queryRedConfirmDetail(itemParam, null);
        if (!ResponseEnum.SUCCESS.getCode().equals(itemResult.getCode())) {
            return Result.ERRORT(itemResult.getCode(), itemResult.getMessage());
        }
        log.info("{}调用DMZ查询数电红字确认单明细成功", LOG_MSG);
        // 更新本地流程表和本地乐企表
        String hzqrxxztdm = itemResult.getData().getHzqrxxztDm();
        approvalHzqrd.setQrrq(result.getData().getQrrq());
        approvalHzqrd.setHzqrxxztdm(hzqrxxztdm);
        approvalHzqrd.setYxbz(CommonEnum.HZQRD_YXBZ_NO.getKey());
        approvalHzqrd.setUpdateTime(new Date());
        approvalHzqrd.setUpdateBy(SecurityUtils.getUserCode());
        vmsApprovalHzqrdService.updateById(approvalHzqrd);

        LambdaQueryWrapper<VmsLeqiHzqrd> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.eq(VmsLeqiHzqrd::getHzfpxxqrdbh, approvalHzqrd.getHzfpxxqrdbh());
        wrapper2.eq(VmsLeqiHzqrd::getQydjid, SecurityUtils.getDeptCode());
        VmsLeqiHzqrd leqiHzqrd = vmsLeqiHzqrdService.getOne(wrapper2);
        if (leqiHzqrd != null) {
            leqiHzqrd.setQrrq(result.getData().getQrrq());
            leqiHzqrd.setHzqrxxztdm(hzqrxxztdm);
            leqiHzqrd.setYxbz(CommonEnum.HZQRD_YXBZ_NO.getKey());
            leqiHzqrd.setUpdateTime(new Date());
            leqiHzqrd.setUpdateBy(SecurityUtils.getUserCode());
            vmsLeqiHzqrdService.updateById(leqiHzqrd);
        }

        return Result.OK();
    }

    @Override
    public Result<VmsApprovalHzqrdTotalSimpleVo> getConfirmDetail(Long applyId) {
        LambdaQueryWrapper<VmsApprovalHzqrd> hzqrdWrapper = new LambdaQueryWrapper<>();
        hzqrdWrapper.eq(VmsApprovalHzqrd::getApplyId, applyId);
        VmsApprovalHzqrd approvalHzqrd = vmsApprovalHzqrdService.getOne(hzqrdWrapper);
        if (approvalHzqrd == null) {
            return Result.ERROR(ResponseEnum.HZQRD_NOT_FIND_ERROR);
        }
        LambdaQueryWrapper<VmsApprovalHzqrdItem> itemWrapper = new LambdaQueryWrapper<>();
        itemWrapper.eq(VmsApprovalHzqrdItem::getHzqrdId, approvalHzqrd.getId());
        itemWrapper.orderByAsc(VmsApprovalHzqrdItem::getXh);
        List<VmsApprovalHzqrdItem> hzqrdItemList = vmsApprovalHzqrdItemService.list(itemWrapper);
        List<VmsApprovalHzqrdItemVo> hzqrdItemVoList = BeanUtils.copyListProperties(hzqrdItemList, VmsApprovalHzqrdItemVo::new, (s, t) -> {
            if (StringUtils.isNotBlank(s.getFpspdj())) {
                t.setDj(s.getFpspdj());
            }
            if (StringUtils.isNotBlank(s.getFpspsl())) {
                t.setSl(s.getFpspsl());
            }
            t.setSlv(s.getSl1());
        });

        VmsApprovalHzqrdTotalSimpleVo totalVo = new VmsApprovalHzqrdTotalSimpleVo();
        VmsApprovalHzqrdSimpleVo hzqrdSimpleVo = new VmsApprovalHzqrdSimpleVo();

        hzqrdSimpleVo.setLzfpdm(approvalHzqrd.getLzfpdm());
        hzqrdSimpleVo.setLzfphm(approvalHzqrd.getLzfphm());
        hzqrdSimpleVo.setHzfpxxqrdbh(approvalHzqrd.getHzfpxxqrdbh());
        hzqrdSimpleVo.setLrfsf(approvalHzqrd.getLrfsf());
        hzqrdSimpleVo.setXsfmc(approvalHzqrd.getXsfmc());
        hzqrdSimpleVo.setXsfnsrsbh(approvalHzqrd.getXsfnsrsbh());
        hzqrdSimpleVo.setGmfmc(approvalHzqrd.getGmfmc());
        hzqrdSimpleVo.setGmfnsrsbh(approvalHzqrd.getGmfnsrsbh());
        hzqrdSimpleVo.setChyydm(approvalHzqrd.getChyydm());
        hzqrdSimpleVo.setChlx(approvalHzqrd.getChlx());
        hzqrdSimpleVo.setGmfsfdkrz(approvalHzqrd.getGmfsfdkrz());

        totalVo.setVmsApprovalHzqrdSimpleVo(hzqrdSimpleVo);
        totalVo.setVmsApprovalHzqrdItemVoList(hzqrdItemVoList);
        return Result.OK(totalVo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<Object> hzqrdConfirm(Long busId, String qrjg) {
        LambdaQueryWrapper<VmsApprovalHzqrd> hzqrdWrapper = new LambdaQueryWrapper<>();
        hzqrdWrapper.eq(VmsApprovalHzqrd::getApplyId, busId);
        VmsApprovalHzqrd hzqrd = vmsApprovalHzqrdService.getOne(hzqrdWrapper);
        if (hzqrd == null) {
            return Result.ERROR(ResponseEnum.HZQRD_NOT_FIND_ERROR);
        }

        // 调用乐企数电红字确认单确认接口完成红字确认单确认
        ConfirmRedConfirmParam param = new ConfirmRedConfirmParam();
        param.setXsfnsrsbh(hzqrd.getXsfnsrsbh());
        param.setUuid(hzqrd.getUuid());
        param.setHzqrdbh(hzqrd.getHzfpxxqrdbh());
        param.setQrlx(qrjg);
        param.setCreateUser(SecurityUtils.getUserCode());
        param.setDeptCode(SecurityUtils.getDeptCode());
        Result<ConfirmRedConfirmVO> result = dmzApiClientService.confirmRedConfirm(param, null);
        if (!ResponseEnum.SUCCESS.getCode().equals(result.getCode())) {
            return Result.ERRORT(result.getCode(), result.getMessage());
        }
        log.info("{}调用DMZ数电红字确认单确认接口完成红字确认单确认成功", LOG_MSG);

        // 调用乐企接口查询数电红字确认单明细信息
        QueryRedConfirmDetailParam itemParam = new QueryRedConfirmDetailParam();
        itemParam.setXsfnsrsbh(hzqrd.getXsfnsrsbh());
        itemParam.setUuid(hzqrd.getUuid());
        itemParam.setCreateUser(SecurityUtils.getUserCode());
        itemParam.setDeptCode(SecurityUtils.getDeptCode());
        Result<QueryRedConfirmDetailVO> itemResult = dmzApiClientService.queryRedConfirmDetail(itemParam, null);
        if (!ResponseEnum.SUCCESS.getCode().equals(itemResult.getCode())) {
            return Result.ERRORT(itemResult.getCode(), itemResult.getMessage());
        }
        log.info("{}调用DMZ查询数电红字确认单明细成功", LOG_MSG);
        // 更新本地流程表和本地乐企表
        hzqrd.setQrrq(result.getData().getQrrq());
        hzqrd.setHzqrxxztdm(itemResult.getData().getHzqrxxztDm());
        hzqrd.setUpdateTime(new Date());
        hzqrd.setUpdateBy(SecurityUtils.getUserCode());
        hzqrd.setApprovalBy(SecurityUtils.getUserCode());
        vmsApprovalHzqrdService.updateById(hzqrd);

        LambdaQueryWrapper<VmsLeqiHzqrd> leqiWrapper = new LambdaQueryWrapper<>();
        leqiWrapper.eq(VmsLeqiHzqrd::getHzfpxxqrdbh, hzqrd.getHzfpxxqrdbh());
        leqiWrapper.eq(VmsLeqiHzqrd::getQydjid, SecurityUtils.getDeptCode());
        VmsLeqiHzqrd leqiHzqrd = vmsLeqiHzqrdService.getOne(leqiWrapper);
        leqiHzqrd.setQrrq(result.getData().getQrrq());
        leqiHzqrd.setHzqrxxztdm(itemResult.getData().getHzqrxxztDm());
        leqiHzqrd.setUpdateTime(new Date());
        leqiHzqrd.setUpdateBy(SecurityUtils.getUserCode());
        vmsLeqiHzqrdService.updateById(leqiHzqrd);

        return Result.OK();
    }

    /**
     * 调用乐企接口同步红字确认单
     */
    private int syncLeqiHzqrd(QueryRedConfirmListParam param, TokenUser tokenUser) {
        int successCount = 0;
        param.setCreateUser(tokenUser.getUserCode());
        param.setDeptCode(tokenUser.getDeptCode());
        Result<QueryRedConfirmListVO> result = dmzApiClientService.queryRedConfirmList(param, null);
        if (ResponseEnum.SUCCESS.getCode().equals(result.getCode())) {
            log.info("{}调用DMZ查询数电红字确认单列表成功", LOG_MSG);

            List<QueryRedConfirmDetailVO> hzqrdList = result.getData().getHzqrxxList().getList();
            if (CollectionUtil.isNotEmpty(hzqrdList)) {
                // 解析乐企返回信息
                for (QueryRedConfirmDetailVO hzqrd : hzqrdList) {
                    try {
                        // 同步单个红字确认单出现异常不影响其他数据继续同步
                        vmsLeqiHzqrdService.syncSingleLeqiHzqrd(hzqrd, tokenUser);
                        successCount = successCount + 1;
                    } catch (Exception e) {
                        log.error("{}同步单个乐企红字确认单出现异常：{}", LOG_MSG, e.getMessage());
                    }
                }
            }
        } else {
            log.error("{}调用DMZ查询数电红字确认单列表失败，原因：{}", LOG_MSG, result.getMessage());
            throw new BusinessException(result.getCode(), result.getMessage());
        }

        return successCount;
    }

    /**
     * 判断红字确认单来源
     *
     * @param hzqrd  红字确认单信息
     * @param nsrsbh 登录机构税号
     * @return 0：我发出的红字确认单 1：我收到的红字确认单
     */
    private String judgeHzqrdSource(VmsLeqiHzqrd hzqrd, String nsrsbh) {
        if (StringUtils.isBlank(nsrsbh)) {
            throw new BusinessException(ResponseEnum.ENTERPRISEINFO_ERROR);
        }
        if (CommonEnum.LRFSF_GMF.getKey().equals(hzqrd.getLrfsf())) {
            return nsrsbh.equals(hzqrd.getGmfnsrsbh()) ? CommonEnum.HZQRD_SOURCE_0.getKey() : CommonEnum.HZQRD_SOURCE_1.getKey();
        } else {
            return nsrsbh.equals(hzqrd.getXsfnsrsbh()) ? CommonEnum.HZQRD_SOURCE_0.getKey() : CommonEnum.HZQRD_SOURCE_1.getKey();
        }
    }

    /**
     * 判断红字确认单冲红类型
     *
     * @param leqiHzqrd 乐企返回红字确认单信息
     * @return 7 部分冲红 8 全部冲红
     */
    private String judgeChlx(VmsLeqiHzqrd leqiHzqrd) {
        String chlx;
        // 蓝字发票已冲销金额合计、已冲销税额合计
        BigDecimal ycxjeTotal = BigDecimal.ZERO, ycxseTotal = BigDecimal.ZERO;

        LambdaQueryWrapper<NvatOutInvoiceDetails> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(NvatOutInvoiceDetails::getFphm, leqiHzqrd.getLzfphm());
        NvatOutInvoiceDetails invoice = nvatOutInvoiceDetailsMapper.selectOne(wrapper1);
        if (invoice == null) {
            // todo 蓝字发票不存在，判断为进项票，冲红类型暂时无法判断
            log.info("{}蓝字发票不存在，判断为进项票，冲红类型暂时无法判断", LOG_MSG);
        } else {
            LambdaQueryWrapper<NvatOutInvomapSelf> selfQuery = new LambdaQueryWrapper<>();
            selfQuery.eq(NvatOutInvomapSelf::getOoidid, invoice.getOidid());
            List<NvatOutInvomapSelf> nvatSelfList = nvatOutInvomapselfMapper.selectList(selfQuery);
            // oracle中的group by不好使，使用stream流根据noidid(红票主表id)去重
            nvatSelfList = nvatSelfList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() ->
                    new TreeSet<>(Comparator.comparing(p -> StringUtil.toString(p.getNoidid())))), ArrayList::new));
            if (CollectionUtil.isNotEmpty(nvatSelfList)) {
                for (NvatOutInvomapSelf nvatSelf : nvatSelfList) {
                    LambdaQueryWrapper<NvatOutInvoiceDetails> invoiceQuery = new LambdaQueryWrapper<>();
                    invoiceQuery.eq(NvatOutInvoiceDetails::getOidid, nvatSelf.getNoidid());
                    NvatOutInvoiceDetails nvatInvoice = nvatOutInvoiceDetailsMapper.selectOne(invoiceQuery);
                    ycxjeTotal = ycxjeTotal.add(nvatInvoice.getHjje().abs());
                    ycxseTotal = ycxseTotal.add(nvatInvoice.getHjse().abs());
                }
            }
        }
        /*
        若蓝字发票合计金额等于蓝字发票已冲销金额加本次冲销金额,
        且蓝字发票合计税额等于蓝字发票已冲销税额加本次冲销税额，则为全部冲红
        */
        if (leqiHzqrd.getLzhjje().abs().compareTo(leqiHzqrd.getHzcxje().abs().add(ycxjeTotal)) == 0
                && leqiHzqrd.getLzhjse().abs().compareTo(leqiHzqrd.getHzcxse().abs().add(ycxseTotal)) == 0) {
            chlx = CommonEnum.INVOICE_STATUS_8.getKey();
        } else {
            chlx = CommonEnum.INVOICE_STATUS_7.getKey();
        }

        return chlx;
    }

}
